package dbx

import (
	"context"
	"fmt"
	"time"

	"github.com/google/uuid"
	"github.com/redis/go-redis/v9"
)

type Redis struct {
	DataBase DataBase `json:"database" yaml:"database" toml:"database"`
	TLS      TLS      `json:"tls,omitempty" yaml:"tls,omitempty" toml:"tls,omitempty"`
}
type RedisSet struct {
	DataBase ReplicaSet `json:"database" yaml:"database" toml:"database"`
	TLS      TLS        `json:"tls,omitempty" yaml:"tls,omitempty" toml:"tls,omitempty"`
}

func (r Redis) Option(handles ...func(*redis.Options)) redis.Options {
	options := redis.Options{
		Username:    r.DataBase.UserName,
		Addr:        r.DataBase.Address,
		Password:    r.DataBase.Password,
		DB:          len(r.DataBase.DbName),
		PoolSize:    10000 >> 2,       // 最大连接数
		DialTimeout: time.Second * 10, // 超时时间
	}
	for _, handle := range handles {
		handle(&options)
	}

	return options
}

func (r RedisSet) Options(handles ...func(*redis.Options)) redis.Options {
	switch len(r.DataBase.Addrs) {
	case 0:
		panic("no database")
	default:
		options := redis.Options{
			ClientName: r.DataBase.RsName,
			Addr:       r.DataBase.Addrs[0],
			Protocol:   0,
			Username:   r.DataBase.UserName,
			Password:   r.DataBase.Password,
		}
		if r.TLS.IsEnable() {
			options.TLSConfig = r.TLS.Tls()
		}

		for _, handle := range handles {
			handle(&options)
		}

		return options
	}
}
func (r RedisSet) ClusterOptions(handles ...func(*redis.ClusterOptions)) redis.ClusterOptions {
	switch len(r.DataBase.Addrs) {
	case 0:
		panic("no database")
	default:
		options := redis.ClusterOptions{
			ClientName: r.DataBase.RsName,
			Addrs:      r.DataBase.Addrs,
			Protocol:   0,
			Username:   r.DataBase.UserName,
			Password:   r.DataBase.Password,
		}
		if r.TLS.IsEnable() {
			options.TLSConfig = r.TLS.Tls()
		}

		for _, handle := range handles {
			handle(&options)
		}

		return options
	}
}
func (r RedisSet) FailoverOptions(handles ...func(*redis.FailoverOptions)) redis.FailoverOptions {
	switch len(r.DataBase.Addrs) {
	case 0:
		panic("no database")
	default:
		options := redis.FailoverOptions{
			MasterName:    r.DataBase.RsName,
			SentinelAddrs: r.DataBase.Addrs,
			ClientName:    uuid.NewString(),
			//SentinelUsername: r.DataBase.Password,
			//SentinelPassword: r.DataBase.UserName,
			Dialer: nil,
			OnConnect: func(ctx context.Context, cn *redis.Conn) error {
				fmt.Println("redis connect success", cn.String())
				return nil
			},
			Protocol:     0,
			Username:     r.DataBase.UserName,
			Password:     r.DataBase.Password,
			PoolSize:     1 << 4,
			PoolTimeout:  5 * time.Second,
			MinIdleConns: 1 << 4,
			MaxIdleConns: 1 << 8,
		}
		if r.TLS.IsEnable() {
			options.TLSConfig = r.TLS.Tls()
		}

		for _, handle := range handles {
			handle(&options)
		}

		return options
	}
}
